/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "灯光.h"

#include <纹理/纹理.h>
//#include "core/设备内存缓存.h"
#include "底层绘图/S_纹理.h"
#include "底层绘图/底层绘图框架.h"

#include "MBT_Engine.h"



S_LightParallel* f_ob_calloc平行光() {
	S_LightParallel* data = (S_LightParallel*)malloc(sizeof(S_LightParallel));
	data->m_color = { 1,1,1 };
	data->m_dir = { 0,-1,0 };
	data->m_falloff = 0;
	data->m_intensity = 1;
	data->m_diffusivity = 0.5;
	return data;
}

S_LightSpot* f_ob_calloc聚光灯() {
	S_LightSpot* data = (S_LightSpot*)malloc(sizeof(S_LightSpot));
	data->m_dir = { 0,-1,0 };
	data->m_pos = { 0,1,0 };
	data->m_falloff = 0;
	data->m_intensity = 1;
	data->m_diffusivity = 0.5;
	return data;
}

S_LightPoint* f_ob_calloc点光源() {
	S_LightPoint* data = (S_LightPoint*)malloc(sizeof(S_LightPoint));
	data->m_pos = { 0,0,0 };
	data->m_intensity = 1;
	data->m_falloff = 0;
	return data;
}

S_LightArea* f_ob_calloc区域光() {
	S_LightArea* data = (S_LightArea*)malloc(sizeof(S_LightArea));
	data->m_dir = { 0,-1,0 };
	data->m_falloff = 0;
	data->m_intensity = 1;
	data->m_color = { 1,1,1 };
	data->m_diffusivity = 0.2;
	return data;
}

void f_ligth_init_区域光(S_LightArea& ligth) {
	ligth.m_dir = { 0, 0, -1 };
	ligth.m_falloff = 0;
	ligth.m_intensity = 1;
	ligth.m_color = { 1,1,1 };
	ligth.m_dis = 1000;

	ligth.m_diffusivity = 0.2;

}

void f_light_free灯光场景数据(S_灯光场景数据* light) {
	switch (light->m_灯光类型) {
		case E_物体类型::t_平行光: {
			f_bm_erase(light->m_灯光数据);
			break;
		}
		case E_物体类型::t_点光源: {
			break;
		}
		case E_物体类型::t_区域光: {
			f_bm_erase(light->m_灯光数据);
			break;
		}
		case E_物体类型::t_聚光灯: {
			break;
		}
		default:
			break;
	}

	for (uint32 i = 0; i < light->m_阴影图->count; ++i) {
		f_tex_销毁纹理(light->m_阴影图->ptr_userData[i]);
		f_fb_销毁帧缓存(light->m_帧缓存->ptr_userData[i]);
	}

	f_bm_erase(light->m_灯光阴影矩阵);
}


void f_light_构建阴影图(S_灯光场景数据* data, uvec2 size, uint32 num) {
	uint32 原有数量 = data->m_阴影图->count;
	if(num == 原有数量) return;

	for (uint32 i = num; i < data->m_阴影图->count; ++i) {
		f_tex_销毁纹理(data->m_阴影图->ptr_userData[i]);
		f_fb_销毁帧缓存(data->m_帧缓存->ptr_userData[i]);
	}

	f_core_array_resize((S_Array*)data->m_阴影图, num);
	f_core_array_resize((S_Array*)data->m_帧缓存, num);

	for (uint32 i = 原有数量; i < data->m_阴影图->count; ++i) {
		auto* tex = f_tex_创建深度纹理(data->m_Ctx, _uVec3(size, 1), E_MS次数::e_MS_1);
		f_tex_安装纹理采样器(tex, f_g_纹理().g_阴影采样器);
		data->m_阴影图->ptr_userData[i] = tex;

		auto* fb = f_fb_创建阴影帧缓存(data->m_Ctx, size, tex);
		data->m_帧缓存->ptr_userData[i] = fb;
	}
}

void f_light_set阴影贴图大小(S_灯光场景数据* data, uvec2 size, int32 层) {
	assert(层 < data->m_阴影图->count);
	if (层 >= 0 && 层 < data->m_阴影图->count) {
		f_tex_setSize(data->m_阴影图->ptr_userData[层], size);
		f_fb_重置阴影帧缓存(data->m_帧缓存->ptr_userData[层], size);
	}
	else {
		for (uint32 i = 0; i < data->m_阴影图->count; ++i) {
			f_tex_setSize(data->m_阴影图->ptr_userData[i], size);
			f_fb_重置阴影帧缓存(data->m_帧缓存->ptr_userData[i], size);
		}
	}
}


float32 f_calculateZFar(float32 fovDegrees, float32 aspectRatio, vec2 WH) {
	const float32 fovRadians = M_角度转弧度(fovDegrees);
	const float32 tanHalfFov = tan(fovRadians / 2.0f);
	// 计算基于宽度和高度的最大深度
	const float32 depthWidth = WH.x / (2.0f * tanHalfFov);
	const float32 depthHeight = WH.y / (2.0f * tanHalfFov / aspectRatio);
	return std::max(depthWidth, depthHeight);
}



Mat44f f_light_计算区域光视口(S_灯光场景数据* data, float32 散度, const Mat44f& mat) {
	S_Viewport cameraView;

	auto lightAtt = f_bm_at<S_LightArea>(data->m_灯光数据, 0);
	//lightAtt.m_color;
	float32 width = length(f_mat44_to_33(mat) * vec3 { lightAtt.m_width, 0, 0 });
	float32 height = length(f_mat44_to_33(mat) * vec3 { lightAtt.m_height, 0, 0 });

	float32 纵横比 = width / height;
	float32 视场角 = lightAtt.m_diffusivity * 180.0 * 1;
	

	Mat44f ProjMatrix{};

	switch (lightAtt.m_samplerType_samplerNum >> 16) {
		case E_投影模式::e_透视: {
			//float32 zf = f_calculateZFar(视场角, 纵横比, { width, height });
			float32 zf = 0.01;
			(*(mat4*)&ProjMatrix) = f_mat4_ProjectionMatrix(视场角, 纵横比, zf, zf + lightAtt.m_dis);
			break;
		}
		case E_投影模式::e_正交: {
			float32 照射距离 = lightAtt.m_dis * 0.5;
			ProjMatrix = f_mat4_Ortho(-width, width, height, -height, -照射距离, 照射距离);
			break;
		}
		default:
			break;
	}
	
	//Mat44f OrthoMatrix = f_mat4_Ortho(-width + 抖动.x, width + 抖动.x, width + 抖动.y, -width + 抖动.y, 0, -1000);
	

	//OrthoMatrix.m10 += 抖动.x;
	//OrthoMatrix.m20 += 抖动.y;

	//float32 m12 = OrthoMatrix.m30;
	//float32 m13 = OrthoMatrix.m31;
	//
	//OrthoMatrix.m30 = m12 * 抖动.y - m13 * 抖动.x;
	//OrthoMatrix.m31 = m12 * 抖动.x + m13 * 抖动.y;
	//
	//OrthoMatrix.m30 = 抖动.x;
	//OrthoMatrix.m31 = 抖动.y;

	//float tiltAngle = 抖动.x; // 例如，30度
	//float tiltRadians = tiltAngle * (3.14159265f / 180.0f); // 转换为弧度
	//float tiltTan = tan(tiltRadians);
	//auto rotMat = f_mat44_identity();
	//rotMat.m00 = cos(抖动.x);
	//rotMat.m01 = -sin(抖动.x);
	//rotMat.m10 = sin(抖动.x);
	//rotMat.m21 = cos(抖动.x);

	//OrthoMatrix *= rotMat;

	//OrthoMatrix.m03 += 抖动.x;
	//OrthoMatrix.m13 += 抖动.y;

	return ProjMatrix;
}




